1、设备树介绍
	设备树是一种描述设备信息的数据结构（是一种树状数据结构），它可以被bootloader传递到内核，从而让内核获得相
应的硬件信息，在内核的sys/firmware/devicetree/base目录中可以查看设备树的节点信息（包括设备树中的各个节点）。
2、DTS、DTB、DTC之间的关系
	设备树源文件后缀为.dts（头文件为.dtsi）、编译后的设备树二进制文件后缀为.dtb、设备树编译器为DTC，.dts文件
可以通过 #include 包含.dtsi、.dts、.h文件，可以通过命令 make ARCH=arm -j8 CROSS_COMPILE=arm-linux-gnueabihf-
 dtbs 编译设备树（其本质是通过makefile调用DTC实现），通过命令dtc -I dtb -o dts xxx.dtb > ***.dts可以对设备树
 进行反编译（xxx编译后的.dtb文件，***反编译后输出的设备树文件，这里要注意DTC工具的目录，它一般位于内核代码的
 scripts/dtc/目录中）。
3、设备树节点
	设备树节点的格式如下：
		[标签:] 名字[@地址] { //中括号中的内容可以省略
			//各种属性
		};
	标签是为了方便在别处引用此节点，地址一般表示设备地址或寄存器首地址。
	跟节点的名字为"/"，每个.dts文件必须要有一个跟节点，当多个设备树文件相互包含是编译器会将多个跟节点合并。
	设备树节点可以嵌套，形成父子节点以及兄弟节点。
	属性实际上是一组键值对，其格式为键=值。
4、常用数据类型
	1）字符串
		用双引号括起来的ASCII码，如compatible = "arm,cortex-a7"中的"arm,cortex-a7"就是字符串（其中compatible
	是属性），可以将多个字符串组合成一个字符串列表，如compatible = "st,stm32mp157d-atk", "st,stm32mp157"。
	2）32位无符号整数
		32位无符号整数采用符号<>表示，如reg = <0>中的0是一个32位无符号整数，可以将多个32位无符号整数组合成一个
	数组，如reg = <0 0x123456 100>，中间用空格隔开。
	3）其他节点
		一个元素可以引用其他节点，并传递引用参数，如quote = <&quote_node 1 2 3>中quote_node并传递了3个参数，
	此外一个元素也可以引用多个节点，如quote = <&quote_node1 1 2 3 &quote_node1 1 2 3>
5、常用的属性
	1）compatible 
		compatible 属性的值是一个字符串列表，用于匹配设备和驱动。一般驱动程序都包含一个设备树匹配表（struct 
	device_driver 对象的 of_match_table 成员），当 compatible 属性中的某一个字符串与设备树匹配表中某个元素的
	compatible 成员所指字符串一样则匹配成功（根节点的compatible则是用于平台匹配）。
	2）model
		model 属性是一个字符串，一般用于描述设备信息。
	3）status
		status 属性是一个字符串，用于表示设备的状态信息。有 "okay"（设备是可操作的）、 "disabled"（设备当前是
	不可操作，但是在可以变为可操作）、 "fail"（设备不可操作，也不大可能变得可操作）、 "fail-sss"（与 "fail" 
	相同，sss表示	检测到的错误内容）。
	4）reg
		reg属性的值一般是 <address length> 对，常用于描述设备地址空间信息。一般格式为reg = <address1 length1 
	address2 length2 address3 length3 ……>
	5）#address-cells 和 #size-cells
		#address-cells 表示 reg 属性中的 address 信息所占字长（32位为一个字，如 #address-cells = 2 则表示每个
	address 信息由2个32位无符号整形组成）， #size-cells 表示 reg 属性中的 length 信息所占字长，为0则表示没有 
	length 信息
	6）ranges
		ranges 属性是按照<子节点地址, 父节点地址, 长度>格式编写的矩阵，它常用于描述子节点地址空间和父节点地址
	空间的对应关系，可以简化子节点中reg属性的编写，其中子节点地址和父节点地址的字长由父节点的 #address-cells 
	确定，长度由父节点的 #size-cells确定。
	7）name
		name 属性值为字符串， name 属性用于记录节点名字， name 属性已经被弃用。
	8）device_type
		device_type 属性值为字符串，用于描述设备的 FCode。
6、追加或修改节点内容
	方法1：
		直接在节点中追加或修改，但是如果此节点的文件被多个平台dts文件包含则相当于修改了多个平台的设备树。
	方法2：
		在跟节点外引用某个节点，然后通过引用进行追加或修改，如要在 i2c1:i2c@021a0000 节点中增加或修改可以采用
	如下方式：
		&i2c1 {
			/* 要追加或修改的属性 */
		};
7、特殊节点
	1、aliases节点
		aliases 节点的主要功能就是定义别名，定义别名的目的就是为了方便访问节点。
	2、chosen节点
		chosen 节点主要引用向操作系统传递参数，其功能类似于 uboot 中的 bootargs，但是 bootargs 优先级更高。
7、查找节点的of函数
	of_find_node_by_name 通过名字查找节点
	of_find_node_by_type 通过节点中的device_type属性查找节点
	of_find_compatible_node 根据节点中的device_type和compatible属性查找节点
	of_find_matching_node_and_match 通过of_device_id匹配表（设备树匹配表）来查找节点
	of_find_node_by_path 通过了解查找节点
8、提取父子节点
	of_get_parent 提取父节点
	of_get_next_child 采用迭代方式提取子节点
9、提取属性值的of函数
	of_find_property 查找指定名字的属性
	of_property_count_elems_of_size 用于获取属性中元素的数量，如获取reg数组的元素个数
	of_property_read_u32_index 从指定属性中提取指定下标的u32数据值
	of_property_read_u8_array 这4个函数分别用于从属性中获取u8、u16、u32或u64类型的数组
	of_property_read_u16_array 
	of_property_read_u32_array 
	of_property_read_u64_array 
	of_property_read_u8  这4个函数分别用于从属性中获取一个u8、u16、u32或u64类型数据
	of_property_read_u16
	of_property_read_u32
	of_property_read_u64
	of_property_read_string 获取属性中字符串的值
	of_n_addr_cells 获取 #address-cells 属性的值
	of_n_size_cells 获取 #size-cells 属性的值
	/* 获取属性引用的节点及传递的值
	 * np 节点
	 * list_name 属性名称
	 * stem_name 被引用的节点中描述在引用此节点时需传递的参数个数的前缀，如gpio节点中的#gpio-cells表示在引用
	 *           gpio节点时需传递的参数个数，这里则应该传递gpio
	 * index 索引
	 * out_args 返回属性引用的节点及传递的参数
	 **/
	int of_parse_phandle_with_args_map(const struct device_node *np, 
										const char *list_name,
										const char *stem_name,
										int index,
										struct of_phandle_args *out_args)
10、其他常用of函数
	of_address_to_resource 将设备树描述的寄存器资源转换为resource结构体类型
	of_irq_to_resource 将设备树描述的中断资源转换为resource结构体类型

